using Cinemachine;
using IQIGame.Onigao.Framework;
using UnityEngine;
using UnityEngine.Events;

namespace IQIGame.Onigao.GameAOT
{
    public static class UnityExtension
    {

        #region Find Component
        public static T GetOrAddComponent<T>(this GameObject gameObject) where T : UnityEngine.Component
        {
            var comp = gameObject.GetComponent<T>();
            if (comp == null)
            {
                comp = gameObject.AddComponent<T>();
            }
            return comp;
        }

        public static T GetOrAddComponent<T>(this GameObject gameObject, bool isAdd) where T : UnityEngine.Component
        {
            if (isAdd)
            {
                return gameObject.AddComponent<T>();
            }
            return GetOrAddComponent<T>(gameObject);
        }

        public static T Find<T>(this Transform transform, string path) where T : UnityEngine.Component
        {
            Transform node = transform.Find(path);
            if (node != null)
            {
                return node.GetComponent<T>();
            }
            return null;
        }

        public static T Find<T>(this GameObject gameOjbect, string path) where T : UnityEngine.Component
        {
            return gameOjbect.transform.Find<T>(path);
        }


        public static GameObject Instantiate(this GameObject go)
        {
            return GameObject.Instantiate(go, go.transform.parent);
        }

        public static GameObject Instantiate(this GameObject go, Transform parent)
        {
            return GameObject.Instantiate(go, parent);
        }

        public static GameObject Instantiate(this GameObject go, GameObject parent)
        {
            return GameObject.Instantiate(go, parent.transform);
        }

        public static void SetLayerRecursively(this GameObject obj, int newLayer)
        {
            if (null == obj)
            {
                return;
            }

            obj.layer = newLayer;

            foreach (Transform child in obj.transform)
            {
                if (null == child)
                {
                    continue;
                }
                SetLayerRecursively(child.gameObject, newLayer);
            }
        }

        public static void SetLayer(this Transform trans, int layerMask)
        {
            foreach (var child in trans.GetComponentsInChildren<Transform>(true))
            {
                child.gameObject.layer = layerMask;
            }
        }

        /// <summary>
        /// 删除transform的子物体,除了exceptTransform
        /// </summary>
        /// <param name="transform"></param>
        /// <param name="destroyImmediate"></param>
        public static void DestroyChildrenExcept(this Transform transform, Transform exceptTransform, bool destroyImmediate = false)
        {
            for (int i = 0; i < transform.childCount; i++)
            {
                Transform child = transform.GetChild(i);
                if (child == exceptTransform)
                    continue;
                if (destroyImmediate)
                    GameObject.DestroyImmediate(transform.GetChild(i).gameObject);
                else
                    GameObject.Destroy(transform.GetChild(i).gameObject);
            }
        }

        #endregion

        #region Transform Position
        /// <summary>
        /// 设置局部坐标
        /// </summary>
        /// <param name="t"></param>
        /// <param name="x"></param>
        public static void SetLocalX(this Transform t, float x)
        {
            var pos = t.localPosition;
            pos.x = x;
            t.localPosition = pos;
        }

        public static void SetLocalY(this Transform t, float y)
        {
            var pos = t.localPosition;
            pos.y = y;
            t.localPosition = pos;
        }

        public static void SetLocalZ(this Transform t, float z)
        {
            var pos = t.localPosition;
            pos.z = z;
            t.localPosition = pos;
        }

        public static float GetLocalX(this Transform t)
        {
            var pos = t.localPosition;
            return pos.x;
        }

        public static float GetLocalY(this Transform t)
        {
            var pos = t.localPosition;
            return pos.y;
        }

        public static float GetLocalZ(this Transform t)
        {
            var pos = t.localPosition;
            return pos.z;
        }

        public static void SetPosX(this Transform t, float x)
        {
            var pos = t.position;
            pos.x = x;
            t.position = pos;
        }

        public static void SetPosY(this Transform t, float y)
        {
            var pos = t.position;
            pos.y = y;
            t.position = pos;
        }

        public static void SetPosZ(this Transform t, float z)
        {
            var pos = t.position;
            pos.z = z;
            t.position = pos;
        }

        public static float GetPosX(this Transform t)
        {
            var pos = t.position;
            return pos.x;
        }

        public static float GetPosY(this Transform t)
        {
            var pos = t.position;
            return pos.y;
        }

        public static float GetPosZ(this Transform t)
        {
            var pos = t.position;
            return pos.z;
        }
        #endregion

        #region UGUI

        public static void AddClickEvent(this ExButton b, UnityAction e)
        {
            b.onClick.AddListener(e);
        }

        #endregion

        #region Camera Cinemachine

        /// <summary>
        /// 瞬间更新镜头
        /// </summary>
        /// <param name="cinemachineBrain"></param>
        public static void ExInstantManualUpdate(this CinemachineBrain cinemachineBrain)
        {
            var old = cinemachineBrain.m_DefaultBlend.m_Style;
            cinemachineBrain.m_DefaultBlend.m_Style = CinemachineBlendDefinition.Style.Cut;
            cinemachineBrain.ManualUpdate();
            cinemachineBrain.m_DefaultBlend.m_Style = old;
        }

        #endregion
        
        
        public static void SafeDestroy(Object rObj)
        {
            if (rObj)
            {
#if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    GameObject.DestroyImmediate(rObj);
                    return;
                }
#endif
                GameObject.Destroy(rObj);
            }
        }

    }
}
